package com.wavercaz.freeforum.controllers;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wavercaz.freeforum.pojo.CommonSearchParam;
import com.wavercaz.freeforum.pojo.User;
import com.wavercaz.freeforum.pojo.UserInfo;
import com.wavercaz.freeforum.pojo.vo.UserVo;
import com.wavercaz.freeforum.services.UserInfoService;
import com.wavercaz.freeforum.services.UserService;
import com.wavercaz.freeforum.services.impl.NewUserDetails;
import com.wavercaz.freeforum.utils.JWTUtil;
import com.wavercaz.freeforum.utils.LoginUtil;
import com.wavercaz.freeforum.utils.QueryUtil;
import com.wavercaz.freeforum.utils.ResponseResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
public class UserController {

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private UserService userService;

    @Autowired
    private BCryptPasswordEncoder bCryptPasswordEncoder;

    @Autowired
    private UserInfoService userInfoService;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private LoginUtil loginUtil;

    // 登录
    @PostMapping("/user/login")
    public ResponseResult login(@RequestBody Map<String,String> loginForm) {
        loginUtil.setType("user");
        Map<String,String> data=new HashMap<>();
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginForm.get("username"), loginForm.get("password"));
        Authentication authenticate = authenticationManager.authenticate(authenticationToken);
        User user1 = (User)((NewUserDetails) authenticate.getPrincipal()).getUserDetail();
        if(user1.getStatus() == 2 ) {
            return new ResponseResult(HttpStatus.FAILED_DEPENDENCY.value(),"该账号已被封禁");
        }
        Map<String,Object> tokenData = new HashMap<>();
        tokenData.put("id",user1.getId());
        data.put("token", JWTUtil.getToken(tokenData));
        return new ResponseResult(HttpStatus.OK.value(),"登录成功",data);
    }

    // 注册
    @PostMapping("/user/register")
    @Transactional
    public ResponseResult register(@RequestBody User registerUser) {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        User user = userService.getOne(queryWrapper.eq("username", registerUser.getUsername()));
        if(user!=null) {
            return new ResponseResult(HttpStatus.NO_CONTENT.value(),"该用户名已存在");
        }
        registerUser.setPassword(bCryptPasswordEncoder.encode(registerUser.getPassword()));
        registerUser.setStatus(1);
        userService.save(registerUser);
        UserInfo userInfo = new UserInfo(null,registerUser.getId(),"/default/defaultUserIcon.png",registerUser.getUsername(),null,null,0,null);
        userInfoService.save(userInfo);
        return new ResponseResult(HttpStatus.OK.value(),"注册成功");
    }

    // 注销
    @PostMapping("/user/logout")
    public ResponseResult logout(@RequestHeader("Authorization") String token) {
        List<String> abandonTokens= (List<String>) redisTemplate.opsForValue().get("abandonTokens");
        if(abandonTokens==null){
            abandonTokens=new ArrayList<>();
        }
        //如果token黑名单有1000条，则截去一半
        if(abandonTokens.size()==1000){
            abandonTokens.subList(499,abandonTokens.size());
        }
        abandonTokens.add(token);
        redisTemplate.opsForValue().set("abandonTokens",abandonTokens);
        return new ResponseResult(HttpStatus.OK.value(),"注销成功");
    }

    // 增
    @PutMapping("/user")
    public ResponseResult save(@RequestBody User user) {
        boolean result = userService.save(user);
        if(!result) return new ResponseResult(HttpStatus.NO_CONTENT.value(), "新增失败");
        else return new ResponseResult(HttpStatus.OK.value(), "新增成功");
    }

    // 删
    @DeleteMapping("/user")
    public ResponseResult delete(@RequestBody List<Integer> ids) {
        boolean result = userService.removeByIds(ids);
        if(!result) return new ResponseResult(HttpStatus.NO_CONTENT.value(), "删除失败");
        else return new ResponseResult(HttpStatus.OK.value(), "删除成功");
    }

    // 改
    @PostMapping("/user")
    public ResponseResult update(@RequestBody User user) {
        boolean result = userService.updateById(user);
        if(!result) return new ResponseResult(HttpStatus.NO_CONTENT.value(), "修改失败");
        else return new ResponseResult(HttpStatus.OK.value(), "修改成功");
    }

    // 查
    @GetMapping("/user/{id}")
    public ResponseResult get(@PathVariable Integer id ) {

        User user = userService.getById(id);
        if(user == null) return new ResponseResult(HttpStatus.NO_CONTENT.value(), "无此相关信息");
        else return new ResponseResult(HttpStatus.OK.value(), user);
    }

    // 列表
    @PostMapping("/userList")
    public ResponseResult list(@RequestBody(required = false) CommonSearchParam commonSearchParam) {
        Object data = null;
        if(commonSearchParam != null) {
            QueryWrapper queryWrapper = QueryUtil.getQueryWrapper(commonSearchParam.getSearches());
            if(commonSearchParam.getPageNum()!=null && commonSearchParam.getPageSize()!=null)
                data= userService.page(new Page<>(commonSearchParam.getPageNum(), commonSearchParam.getPageSize()), queryWrapper);
            else data= userService.list(queryWrapper);
        }
        else data= userService.list();
        return new ResponseResult(HttpStatus.OK.value(), data);
    }

    // vo列表
    @PostMapping("/userVoList")
    public ResponseResult listVo(@RequestBody(required = false) CommonSearchParam commonSearchParam) {
        IPage<UserVo> data = userService.getUserVoList(commonSearchParam, new Page<>(commonSearchParam.getPageNum(), commonSearchParam.getPageSize()));
        return new ResponseResult(HttpStatus.OK.value(), data);

    }
}
